var whenReady = (function () {
    var funcs = [];
    var ready = false;

    function handler(e) {
        if (ready) {
            return;
        }

        if (e.type === 'onreadystatechange' && document.readyState !== 'complete') {
            return;
        }

        for (var i = 0; i < funcs.length; i++) {
            funcs[i].call(document);
        }
        ready = true;
        funcs = null;
    }
    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', handler, false);
        document.addEventListener('readystatechange', handler, false);
        window.addEventListener('load', handler, false);
    } else if (document.attachEvent) {
        document.attachEvent('onreadystatechange', handler);
        window.attachEvent('onload', handler);
    }
    return function whenReady(fn) {
        if (ready) {
            fn.call(document);
        } else {
            funcs.push(fn);
        }
    }
})();

whenReady(function () {
    var defaultImageData = '';

    function aesEncrypt(word, keyWord) {
        var key = CryptoJS.enc.Utf8.parse(keyWord);
        var srcs = CryptoJS.enc.Utf8.parse(word);
        var encrypted = CryptoJS.AES.encrypt(srcs, key, {
            mode:CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return encrypted.toString();
    }

    function uuid() {
        var s = [];
        var hexDigits = '0123456789abcdef';
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = '4'
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        s[8] = s[13] = s[18] = s[23] = '-';
        return s.join('');
    }

    function doPost(url, data, resolve, reject) {
        axios.post(url, data).then(function (response) {
            if (resolve) resolve(response);
        }).catch(function (error) {
            if (reject) reject(error);
        });
    }

    function getImage(baseUrl, data, resolve, reject) {
        doPost(baseUrl + '/getCaptcha', data, resolve, reject);
    }

    function checkImage(baseUrl, data, resolve, reject) {
        doPost(baseUrl + '/checkCaptcha', data, resolve, reject);
    }

    var ModalVerify = function (selectors, options) {
        this.defaults = {
            baseUrl: '/api',
            captchaType: 'blockPuzzle',
            title: '请完成安全验证',
            explain : '向右滑动完成验证',
            vOffset: 5,
            beforeCheck: function () { return true; },
            ready : function () {},
            success : function (data) {},
            error : function (err) {}
        };
        this.selectors = selectors;
        this.options = this.defaults;
        if (options) {
            for (var prop in options) {
                this.options[prop] = options[prop];
            }
        }
        this.backToken = null;
        this.moveLeftDistance = 0;
        this.secretKey = '';
        this.status = false;
        this.isEnd = false;
        if (!localStorage.getItem('ModalVerify')) {
            localStorage.setItem('ModalVerify', uuid());
        }
    };

    ModalVerify.prototype = {
        init: function () {
            var _this = this;
            _this.element = document.querySelector(_this.selectors);
            _this.loadDom();
            _this.refresh();
            _this.modal = new bootstrap.Modal(_this.selectors, {
                backdrop: 'static',
                keyboard: false
            });
            _this.options.ready();
            this.element.onselectstart = document.body.ondrag = function () {
                return false;
            };
            this.htmlDoms.moveBlock.ontouchstart = function (e) {
                _this.start(e);
            };
            this.htmlDoms.moveBlock.onmousedown = function (e) {
                _this.start(e);
            };
            this.htmlDoms.subBlock.onmousedown = function (e) {
                e.stopPropagation();
            };
            this.htmlDoms.refresh.onclick = function () {
                _this.refresh(true);
            };
            window.addEventListener('touchmove', function (e) {
                _this.move(e);
            });
            window.addEventListener('mousemove', function (e) {
                _this.move(e);
            });
            window.addEventListener('touchend', function () {
                _this.end();
            });
            window.addEventListener('mouseup', function () {
                _this.end();
            });
            return _this;
        },

        loadDom: function () {
            this.element.classList.add('modal');
            this.element.classList.add('fade');
            this.element.tabIndex = -1;
            var html = '' +
                '<div class="modal-dialog">' +
                    '<div class="modal-content">' +
                        '<div class="modal-header">' +
                            '<span class="modal-title"></span>' +
                            '<button type="button" class="btn-close" data-bs-dismiss="modal"></button>' +
                        '</div>' +
                        '<div class="modal-body">' +
                            '<p>Hello</p>' +
                        '</div>' +
                    '</div>' +
                '</div>';
            this.element.innerHTML = html;
            this.htmlDoms = {
                modalBody: this.element.querySelector('.modal-body')
            };
            html = '' +
                '<div class="verify-image-panel">' +
                    '<img>' +
                    '<div class="verify-tips alert"></div>' +
                    '<div class="verify-refresh"></div>' +
                '</div>' +
                '<div class="verify-bar-area">' +
                    '<span class="verify-message"></span>' +
                    '<div class="verify-left-bar">' +
                        '<div class="verify-move-block">' +
                            '<div class="verify-sub-block">' +
                                '<img>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                '</div>';
            this.htmlDoms.modalBody.innerHTML = html;
            this.htmlDoms.imagePanel = this.element.querySelector('.verify-image-panel');
            this.htmlDoms.image = this.element.querySelector('.verify-image-panel img');
            this.htmlDoms.tips = this.element.querySelector('.verify-tips');
            this.htmlDoms.refresh = this.element.querySelector('.verify-refresh');
            this.htmlDoms.barArea = this.element.querySelector('.verify-bar-area');
            this.htmlDoms.message = this.element.querySelector('.verify-message');
            this.htmlDoms.leftBar = this.element.querySelector('.verify-left-bar');
            this.htmlDoms.moveBlock = this.element.querySelector('.verify-move-block');
            this.htmlDoms.subBlock = this.element.querySelector('.verify-sub-block');
            this.htmlDoms.blockImage = this.element.querySelector('.verify-sub-block img');
            this.element.querySelector('.modal-dialog').style.width = '346px';
            this.element.querySelector('.modal-title').innerText = this.options.title;
            this.htmlDoms.message.innerText = this.options.explain;
        },

        show: function () {
            this.modal.show();
        },

        hide: function () {
            this.modal.hide();
        },

        start: function (e) {
            var x = e.targetTouches ? e.targetTouches[0].pageX : e.clientX;
            var error = this.htmlDoms.blockImage.classList.contains('error');
            var refreshing = this.htmlDoms.refresh.classList.contains('refreshing');
            this.barAreaLeft = this.htmlDoms.barArea.getBoundingClientRect().left;
			this.startLeft = Math.floor(x - this.barAreaLeft);
			this.startMoveTime = new Date().getTime();
        	if (!this.isEnd && !error && !refreshing) {
	        	this.htmlDoms.message.innerText = '';
                this.htmlDoms.moveBlock.classList.add('draggable');
	        	e.stopPropagation();
	        	this.status = true;
        	}
        },

        move: function (e) {
        	if (this.status && !this.isEnd) {
        	    var x = e.touches ? e.touches[0].pageX : e.clientX;
				var moveBlockLeft = x - this.barAreaLeft;
				moveBlockLeft = Math.floor(Math.min(Math.max(moveBlockLeft - this.startLeft + 40, 40), 310));
				this.htmlDoms.leftBar.style.width = moveBlockLeft + 'px';
				this.moveLeftDistance = moveBlockLeft;
	        }
        },

        end: function() {
            var _this = this;
            _this.endMovetime = new Date().getTime();
            if (_this.status && !_this.isEnd) {
                if (!_this.options.beforeCheck()) {
                    return;
                }
                var vOffset = parseInt(_this.options.vOffset);
                var point = JSON.stringify({ x: _this.moveLeftDistance - 40, y: vOffset });
				var data = {
					captchaType: _this.options.captchaType,
					pointJson: _this.secretKey ? aesEncrypt(point, _this.secretKey) : point,
					token: _this.backToken,
					clientUid: localStorage.getItem('ModalVerify'),
					ts: Date.now()
				}
				var verification = _this.backToken + '---'+ point;
				var captchaVerification = this.secretKey ? aesEncrypt(verification ,this.secretKey) : verification;
                checkImage(_this.options.baseUrl, data, function (response) {
                    if (response.data.repCode === '0000') {
                        _this.htmlDoms.tips.classList.remove('alert-danger');
                        _this.htmlDoms.tips.classList.add('alert-success');
                        _this.htmlDoms.tips.classList.remove('hide');
                        _this.htmlDoms.tips.classList.add('show');
                        _this.htmlDoms.tips.innerText = '验证成功';
                        _this.isEnd = true;
                        var timeoutId = setTimeout(function () {
                            clearTimeout(timeoutId);
                            _this.hide();
                            _this.htmlDoms.tips.classList.remove('show');
                            _this.htmlDoms.tips.classList.add('hide');
                            _this.refresh();
                        }, 1000);
                        _this.options.success({ captchaVerification: captchaVerification });
                    } else {
                        _this.htmlDoms.tips.classList.remove('alert-success');
                        _this.htmlDoms.tips.classList.add('alert-danger');
                        _this.htmlDoms.tips.classList.remove('hide');
                        _this.htmlDoms.tips.classList.add('show');
                        _this.htmlDoms.tips.innerText = response.data.repMsg;
                        var timeoutId = setTimeout(function () {
                            clearTimeout(timeoutId);
                            _this.htmlDoms.tips.classList.remove('show');
                            _this.htmlDoms.tips.classList.add('hide');
                            _this.refresh();
                        }, 1000);
                        _this.options.error(response.data);
                    }
                });
                _this.status = false;
            }
            _this.htmlDoms.moveBlock.classList.remove('draggable');
        },

        refresh: function (flag) {
            var _this = this;
            var data = {
                captchaType: _this.options.captchaType,
                clientUid: localStorage.getItem('ModalVerify'),
                ts: Date.now()
            };
            var startTime = new Date().getTime();
            if (flag) {
                if (_this.htmlDoms.refresh.classList.contains('refreshing')) {
                    return;
                }
                _this.htmlDoms.refresh.classList.add('refreshing');
            }
            _this.htmlDoms.leftBar.style.width = '40px';
            _this.htmlDoms.message.innerText = _this.options.explain;
            _this.isEnd = false;
			getImage(_this.options.baseUrl, data, function (response) {
			    if (flag) {
                    var time = 1000 - (new Date().getTime() - startTime);
                    if (time <= 0) {
                        _this.htmlDoms.refresh.classList.remove('refreshing');
                    } else {
                        var timeoutId = setTimeout(function () {
                            clearTimeout(timeoutId);
                            _this.htmlDoms.refresh.classList.remove('refreshing');
                        }, time);
                    }
                }
				if (response.data.repCode === '0000') {
					_this.htmlDoms.image.src = 'data:image/png;base64,' + response.data.repData.originalImageBase64;
					_this.htmlDoms.blockImage.src = 'data:image/png;base64,' + response.data.repData.jigsawImageBase64;
					_this.htmlDoms.blockImage.classList.remove('error');
                    _this.htmlDoms.tips.classList.remove('show');
                    _this.htmlDoms.tips.classList.remove('hide');
					_this.secretKey = response.data.repData.secretKey;
					_this.backToken = response.data.repData.token;
				} else {
				    _this.htmlDoms.image.src = defaultImageData;
				    _this.htmlDoms.blockImage.src = defaultImageData;
				    _this.htmlDoms.blockImage.classList.add('error');
                    _this.htmlDoms.tips.classList.remove('alert-success');
                    _this.htmlDoms.tips.classList.add('alert-danger');
                    _this.htmlDoms.tips.classList.remove('hide');
                    _this.htmlDoms.tips.classList.add('show');
                    _this.htmlDoms.tips.innerText = response.data.repMsg;
                    var timeoutId = setTimeout(function () {
                        _this.htmlDoms.tips.classList.remove('show');
                        _this.htmlDoms.tips.classList.add('hide');
                    }, 1000);
				}
			});
        }
    };

    window.ModalVerify = ModalVerify;
});
